package com.shaoyu.elasticsearch.service.util;

import com.shaoyu.elasticsearch.service.fulltext.FullTextSearchService;
import com.shaoyu.elasticsearch.service.fulltext.TermSearchService;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;

import java.util.Map;

public class QueryBuilderUtil {

    public static QueryBuilder getQuery(Map<String, Object> param) {
        if (param.get(FullTextSearchService.MATCH_QUERY) != null) {
            Map<String, String> p = (Map<String, String>) param.get(FullTextSearchService.MATCH_QUERY);
            return matchQuery(p.get("field"), p.get("text"));
        } else if (param.get(FullTextSearchService.MULTI_MATCH_QUERY) != null) {
            Map<String, String> p = (Map<String, String>) param.get(FullTextSearchService.MULTI_MATCH_QUERY);
            return multiMatchQuery(p.get("text"), p.get("fields").split(FullTextSearchService.MULTI_MATCH_QUERY_FILEDS_SPLIT));
        } else if (param.get(FullTextSearchService.COMMON_TERMS_QUERY) != null) {
            Map<String, String> p = (Map<String, String>) param.get(FullTextSearchService.COMMON_TERMS_QUERY);
            return commonTermsQuery(p.get("field"), p.get("value"));
        } else if (param.get(FullTextSearchService.QUERY_STRING_QUERY) != null) {
            //QueryBuilder qb = queryStringQuery("+kimchy -elasticsearch");   //text
            Map<String, String> p = (Map<String, String>) param.get(FullTextSearchService.QUERY_STRING_QUERY);
            return queryStringQuery(p.get("text"));
        } else if (param.get(FullTextSearchService.SIMPLE_QUERY_STRING) != null) {
            Map<String, String> p = (Map<String, String>) param.get(FullTextSearchService.SIMPLE_QUERY_STRING);
            return simpleQueryString(p.get("text"));
        } else if(param.get(TermSearchService.RANG_QUERY)!=null){
            Map<String, String> p = (Map<String, String>) param.get(TermSearchService.RANG_QUERY);
            return rangeQuery(p);
        }else if(param.get(TermSearchService.TERM_QUERY)!=null){
            Map<String, String> p = (Map<String, String>) param.get(TermSearchService.RANG_QUERY);
            return termQuery(p.get("field"),p.get("text"));
        }else if(param.get(TermSearchService.TERMS_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.TERMS_QUERY);
            return termsQuery(p.get("field"),p.get("values"));
        }else if(param.get(TermSearchService.EXISTS_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.EXISTS_QUERY);
            return QueryBuilders.existsQuery(p.get("name"));
        }else if(param.get(TermSearchService.PREFIX_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.PREFIX_QUERY);
            return QueryBuilders.prefixQuery(p.get("name"),p.get("prefix"));
        }else if(param.get(TermSearchService.WILDCARD_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.WILDCARD_QUERY);
            return QueryBuilders.wildcardQuery(p.get("name"),p.get("query"));
        }else if(param.get(TermSearchService.REGEXP_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.REGEXP_QUERY);
            return QueryBuilders.regexpQuery(p.get("name"),p.get("regexp"));
        }else if(param.get(TermSearchService.FUZZY_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.FUZZY_QUERY);
            return QueryBuilders.fuzzyQuery(p.get("name"),p.get("value"));
        }else if (param.get(TermSearchService.TYPE_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.TYPE_QUERY);
            return QueryBuilders.typeQuery(p.get("type"));
        }else if (param.get(TermSearchService.IDS_QUERY)!=null){
            Map<String,String>p=(Map<String, String>) param.get(TermSearchService.IDS_QUERY);
            return idsQuery(p);
        }
        return null;
    }

    private static QueryBuilder idsQuery(Map<String, String> p) {
        if(p.get("types")!=null){
            return QueryBuilders.idsQuery(p.get("types").split(",")).addIds(p.get("ids").split(","));
        }else{
            return QueryBuilders.idsQuery().addIds(p.get("ids").split(","));
        }
    }

    private static QueryBuilder termsQuery(String field, String values) {
        return QueryBuilders.termsQuery(field,values.split(","));
    }

    private static QueryBuilder termQuery(String field, String text) {
        return QueryBuilders.termQuery(field,text);
    }


    private static QueryBuilder simpleQueryString(String text) {
        return QueryBuilders.simpleQueryStringQuery(text);
    }

    /**
     * 范围查询<br/>
     * gte() :范围查询将匹配字段值大于或等于此参数值的文档。<br/>
     * gt() :范围查询将匹配字段值大于此参数值的文档。<br/>
     * lte() :范围查询将匹配字段值小于或等于此参数值的文档。<br/>
     * lt() :范围查询将匹配字段值小于此参数值的文档。<br/>
     * from() 开始值 to() 结束值 这两个函数与includeLower()和includeUpper()函数配套使用。<br/>
     * includeLower(true) 表示 from() 查询将匹配字段值大于或等于此参数值的文档。<br/>
     * includeLower(false) 表示 from() 查询将匹配字段值大于此参数值的文档。<br/>
     * includeUpper(true) 表示 to() 查询将匹配字段值小于或等于此参数值的文档。<br/>
     * includeUpper(false) 表示 to() 查询将匹配字段值小于此参数值的文档。<br/>
     * 其中,参数若没有includeLower/includeUpper 将默认为false。
     * @param p
     * @return
     */
    private static QueryBuilder rangeQuery(Map<String, String> p) {
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(p.get("field"));
        boolean flag = false;
        if(p.get("gt")!=null){
            rangeQueryBuilder.gt(p.get("gt"));
            flag = true;
        }
        if(p.get("gte")!=null){
            rangeQueryBuilder.gte(p.get("gte"));
            flag = true;
        }
        if(p.get("lte")!=null){
            rangeQueryBuilder.lte(p.get("lte"));
            flag = true;
        }
        if(p.get("lt")!=null){
            rangeQueryBuilder.lt(p.get("lt"));
            flag = true;
        }
        if(p.get("from")!=null){
            rangeQueryBuilder.from(p.get("from"));
            if(p.get("includeLower")!=null){
                rangeQueryBuilder.includeLower(Boolean.parseBoolean(p.get("includeLower")));
            }else{
                rangeQueryBuilder.includeLower(false);
            }
            flag = true;
        }
        if(p.get("to")!=null){
            rangeQueryBuilder.to(p.get("to"));
            if(p.get("includeUpper")!=null){
                rangeQueryBuilder.includeUpper(Boolean.parseBoolean(p.get("includeUpper")));
            }else{
                rangeQueryBuilder.includeUpper(false);
            }
            flag = true;
        }
        //只有字段没有任何条件不做条件过滤
        if(!flag)return null;
        return rangeQueryBuilder;
    }

    /**
     *  匹配查询
     * @param name
     * @param text
     * @return
     */
    private static QueryBuilder matchQuery(String name, String text) {
        return QueryBuilders.matchQuery(name,text);
    }

    private static QueryBuilder queryStringQuery(String text) {
        return QueryBuilders.queryStringQuery(text);
    }

    private static  QueryBuilder commonTermsQuery(String field, String value) {
        return QueryBuilders.commonTermsQuery(field,value);
    }

    private static  QueryBuilder multiMatchQuery(String text, String[] fields) {
        return QueryBuilders.multiMatchQuery(text,fields);
    }

}
